package com.example.springboot.service.sys.Impl;

import com.alibaba.fastjson.JSON;
import com.example.springboot.config.Shiro.security.MySessionManager;
import com.example.springboot.config.Shiro.security.SecurityConstants;
import com.example.springboot.config.Shiro.security.SecurityUtil;
import com.example.springboot.config.Shiro.security.SpringUtils;
import com.example.springboot.mapper.CmsUserRoleMapper;
import com.example.springboot.model.entity.CmsUser;
import com.example.springboot.model.entity.CmsUserRole;
import com.example.springboot.model.enums.ResultCodeEnum;
import com.example.springboot.model.form.PageUtil;
import com.example.springboot.model.form.Result;
import com.example.springboot.model.req.sys.LoginReq;
import com.example.springboot.model.sys.SysUser;
import com.example.springboot.model.sys.UserInfoVO;
import com.example.springboot.service.sys.CmsUserService;
import com.example.springboot.service.sys.LoginService;
import com.example.springboot.service.sys.SuSmsLogService;
import com.example.springboot.utils.Assert;
import com.example.springboot.utils.CopyUtil;
import com.example.springboot.utils.RandomUtil;
import com.example.springboot.utils.RedisUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

@Service
public class LoginServiceImpl implements LoginService {

    private final static String LOGIN_SESSION_KEY_PREFIX = "zf_";
    @Resource
    CmsUserService cmsUserService;
    @Resource
    SuSmsLogService suSmsLogService;
    @Resource
    MySessionManager mySessionManager;

    @Resource
    RedisUtil redisUtil;
    @Resource
    private CmsUserRoleMapper cmsUserRoleMapper;

    @Override
    public Object login(LoginReq req) {
        Result result;
        try {
            if (!SpringUtils.testEnv()) {
                Result checkResult = suSmsLogService.checkMobileMessage(req.getMobile(), req.getCode());
                if (!checkResult.success()) {
                    return Result.with(ResultCodeEnum.CHECK_CODE_ERROR);
                }
            }
            //获取当前用户
            Subject subject = SecurityUtils.getSubject();
            //用户登陆数据
            UsernamePasswordToken token = new UsernamePasswordToken(req.getMobile(), req.getPassword());
            subject.login(token);

            String currentSessionId = subject.getSession().getId().toString();
            String cacheKey = LOGIN_SESSION_KEY_PREFIX + req.getMobile();
            redisUtil.lSet(cacheKey, currentSessionId, SecurityConstants.SESSION_TIMEOUT / 1000);
            List<Object> sl = redisUtil.lGet(cacheKey, 0, -1);
            for (Object obj : sl) {
                String loginSessionId = (String) obj;
                if (!loginSessionId.equals(currentSessionId)) {
                    redisUtil.lRemove(cacheKey, 10, obj);
                    Session session = mySessionManager.getSessionDAO().readSession(loginSessionId);
                    if (session != null) {
                        mySessionManager.getSessionDAO().delete(session);
                    }
                }
            }
            SysUser user = SecurityUtil.sysUser();
            UserInfoVO userInfoVO = CopyUtil.copyObject(user, UserInfoVO.class);
            userInfoVO.setToken(subject.getSession().getId().toString());
            userInfoVO.setRoleName(user.getRoles().get(0).getName());

            result = Result.with(userInfoVO);
        } catch (IncorrectCredentialsException e) {
            System.out.println(JSON.toJSONString(e));
            result = Result.with(ResultCodeEnum.PASSWORD_ERROR);
        } catch (LockedAccountException e) {
            System.out.println(JSON.toJSONString(e));
            result = Result.with(ResultCodeEnum.USER_INVALID);
        } catch (AuthenticationException e) {
            System.out.println(JSON.toJSONString(e));
            result = Result.with(ResultCodeEnum.USER_NOT_EXIST);
        } catch (Exception e) {
            System.out.println(JSON.toJSONString(e));
            result = Result.with(ResultCodeEnum.INNER_ERROR);
        }
        return result;
    }


    @Override
    @Transactional
    public Result signIn(LoginReq req) {
        // 查询手机号是否存在
        CmsUser userMobile = cmsUserService.getOne(PageUtil.getQueryWrapper(new CmsUser())
                .eq(CmsUser::getMobile, req.getMobile())
                .eq(CmsUser::getInvalid, 0));
        Assert.notNull(userMobile, ResultCodeEnum.MOBILE_REPETITION_ERROR);

        // 查询账号是否存在
        CmsUser userAccount = cmsUserService.getOne(PageUtil.getQueryWrapper(new CmsUser())
                .eq(CmsUser::getUsername, req.getUsername())
                .eq(CmsUser::getInvalid, 0));
        Assert.notNull(userAccount, ResultCodeEnum.USER_ALREADY_EXIST);

        // 查询邮箱是否存在
        CmsUser userEmail = cmsUserService.getOne(PageUtil.getQueryWrapper(new CmsUser())
                .eq(CmsUser::getMailbox, req.getMailbox())
                .eq(CmsUser::getInvalid, 0));
        Assert.notNull(userEmail, ResultCodeEnum.EMAIL_ALREADY_EXIST);

        CmsUser cmsUser = new CmsUser();
        cmsUser.setMobile(req.getMobile());
        // 密码加密
        cmsUser.setSalt(RandomUtil.userSalt());
        cmsUser.setPassword(SecurityUtil.encodePassword(req.getPassword(), cmsUser.getSalt()));
        cmsUser.setMailbox(req.getMailbox());
        cmsUser.setUsername(req.getUsername());
        if (cmsUserService.save(cmsUser)) {
            CmsUserRole role = new CmsUserRole();
            role.setUserId(cmsUser.getId());
            //默认角色为用户
            role.setRoleId(2);
            int insert = cmsUserRoleMapper.insert(role);
            if (insert > 0) {
                return Result.buildSuccess();
            }
        }
        return Result.buildFail();
    }

    @Override
    public Result updatePwd(String oldPwd, String newPwd) {

        CmsUser cmsUser = cmsUserService.getById(SecurityUtil.sysUser().getId());
        if (cmsUser == null) {
            return Result.with(ResultCodeEnum.USER_NOT_EXIST);
        }
        //校验原密码
        if (!cmsUser.getPassword().equals(SecurityUtil.encodePassword(oldPwd, cmsUser.getSalt()))) {
            return Result.buildFail("原密码不正确!");
        }

        //修改密码
        cmsUser.setPassword(SecurityUtil.encodePassword(newPwd, cmsUser.getSalt()));
        if (cmsUserService.updateById(cmsUser)) {
            return Result.buildSuccess();
        }

        return Result.buildFail();
    }

    @Override
    public Result updateDefaultPwd(String mobile) {
        String password = "$@$tz1@@7ndq8jypnifo";
        Assert.isEmpty(mobile, ResultCodeEnum.CLIENT_PARAM_ERROR);
        CmsUser cmsUser = cmsUserService.getOne(PageUtil.getQueryWrapper(new CmsUser())
                .eq(CmsUser::getMobile, mobile)
                .eq(CmsUser::getInvalid, 0), false);
        if (cmsUser == null || cmsUser.getId() == null) {
            return Result.buildFail("请输入有效手机号");
        }
        cmsUser.setPassword(SecurityUtil.encodePassword(password, cmsUser.getSalt()));
        if (cmsUserService.updateById(cmsUser)) {
            return Result.with(password);
        }
        return Result.buildFail();
    }


}
